package cricket

import (
	"github.com/spf13/cast"
	"go.uber.org/atomic"
	global2 "longmen/server/config/global"
	cricket_behaviour2 "longmen/server/internal/services/nami/api/v5/sports/cricket/cricket_behaviour"
	"longmen/server/internal/services/nami/config"
	cricket2 "longmen/server/internal/services/nami/services/sports/cricket"
	"longmen/server/internal/services/nami/services/sports/cricket/crcache"
	"longmen/server/internal/services/nami/utils"
	"longmen/server/internal/services/nami/utils/restyclient"
	"longmen/server/pkg/db/mysql/models/models_sports"
	"time"
)

// Cricket 内部实现接口
type Cricket struct{}

// SyncCategory 获取分类列表
// 返回全量分类数据
// 数据很少变动，建议请求频次：1天/次
func (f Cricket) SyncCategory() {
	global2.Log.Info("板球 同步 [分类] - 开始")
	resp := cricket_behaviour2.CategoryApiResponse{}
	err := restyclient.GetUrlAndBindRecords(config.CRCategoryUrl+config.BuildParamsAndUserAndSecret(), &resp)
	if err != nil {
		global2.Log.Error("获取板球赛事分类失败: ", err)
		return
	}
	// 调用入库
	cricket2.CrateCategory(resp.Interface())
}

// SyncCountry 获取国家列表
// 返回全量国家数据
//
// 数据很少变动，建议请求频次：1天/次
func (f Cricket) SyncCountry() {
	global2.Log.Info("板球 同步 [国家] - 开始")
	resp := cricket_behaviour2.CountryApiResponse{}
	err := restyclient.GetUrlAndBindRecords(config.CRCountryUrl+config.BuildParamsAndUserAndSecret(), &resp)
	if err != nil {
		global2.Log.Error("获取板球国家列表失败: ", err)
		return
	}
	// 调用入库
	cricket2.CrateCountry(resp.Interface())
}

func (f Cricket) SyncCompetition() () {
	f.SyncUniqueTournament()
}

// SyncUniqueTournament 获取赛事列表
// 返回全量赛事数据，可根据时间戳增量获取新增或变动的数据
//
// 1、首次全量更新，根据参数id获取全量数据 (在cricket_init.go 中进行全量手动初始化)
// 2、后续增量更新，根据参数time增量获取变动数据（建议请求频次：1min/次）
func (f Cricket) SyncUniqueTournament() {
	global2.Log.Info("板球 同步 [赛事] - 开始")
	resp := cricket_behaviour2.UniqueTournamentApiResponse{}
	maxId := cricket2.GetUniqueTournamentId()
	queryStr := config.BuildParamsAndUserAndSecret(map[string]interface{}{
		"id":    maxId,
		"limit": 1000,
	})
	err := restyclient.GetUrlAndBindRecords(config.CRUniqueTournamentUrl+queryStr, &resp)
	if err != nil {
		global2.Log.Error("获取板球赛事列表失败: ", err)
		return
	}
	// 调用入库
	cricket2.CrateUniqueTournament(resp.Interface())
}

// SyncVenue 获取赛事列表
// 返回全量赛事数据，可根据时间戳增量获取新增或变动的数据
//
// 1、首次全量更新，根据参数id获取全量数据 (在cricket_init.go 中进行全量手动初始化)
// 2、后续增量更新，根据参数time增量获取变动数据（建议请求频次：1min/次）
func (f Cricket) SyncVenue() {
	global2.Log.Info("板球 同步 [场馆] - 开始")
	resp := cricket_behaviour2.VenueApiResponse{}
	startTime := cricket2.GetVenueTime()
	queryStr := config.BuildParamsAndUserAndSecret(map[string]interface{}{
		"time":  startTime,
		"limit": 1000,
	})
	err := restyclient.GetUrlAndBindRecords(config.CRVenue+queryStr, &resp)
	if err != nil {
		global2.Log.Error("获取板球场馆列表失败: ", err)
		return
	}
	// 调用入库
	cricket2.CrateVenue(resp.Results)
}

// SyncTeam 获取球队列表
// 返回全量球队数据，可根据时间戳增量获取新增或变动的数据
//
// 1、首次全量更新，根据参数id获取全量数据
// 2、后续增量更新，根据参数time增量获取变动数据（建议请求频次：1min/次）
func (f Cricket) SyncTeam() {
	global2.Log.Info("板球 同步 [球队] - 开始")
	resp := cricket_behaviour2.TeamApiResponse{}
	maxId := cricket2.GetTeamMaxId()
	global2.Log.Debugf("板球球队最大id:%v", maxId)
	queryStr := config.BuildParamsAndUserAndSecret(map[string]interface{}{
		"id":    maxId,
		"limit": 1000,
	})
	err := restyclient.GetUrlAndBindRecords(config.CRTeamsUrl+queryStr, &resp)
	if err != nil {
		global2.Log.Error("获取板球球队列表失败: ", err)
		return
	}
	// 调用入库
	cricket2.CrateTeam(resp.Interface())
}

// SyncMatch 获取赛程赛果列表-日期查询
// 该接口返回所请求日期的全量赛程赛果数据（请求限制：前后30天）
// 注：实时数据的获取通过实时统计数据接口
//
// 当天赛程 建议请求频次：10min/次（全量更新）
func (f Cricket) SyncMatch() {
	// 当天赛程
	today := time.Now().Format("20060102")
	syncMatch(today)
}

func syncMatch(today string) {
	resp := cricket_behaviour2.MatchApiResponse{}
	queryStr := config.BuildParamsAndUserAndSecret(map[string]interface{}{
		"date": today,
	})
	err := restyclient.GetUrlAndBindRecords(config.CRMatchDiaryUrl+queryStr, &resp)
	if err != nil {
		global2.Log.Error("获取板球赛程列表失败: ", err)
		return
	}
	// 调用入库
	cricket2.CrateMatch(resp.Interface())
}

func (f Cricket) SyncMatchByDate(date string) {
	syncMatch(date)
}

// SyncFutureMatch 获取赛程赛果列表-日期查询
// 该接口返回所请求日期的全量赛程赛果数据（请求限制：前后30天）
// 注：实时数据的获取通过实时统计数据接口
//
// 未来赛程 建议请求频次：30min/次（全量更新）
func (f Cricket) SyncFutureMatch() {
	for i := 1; i <= 7; i++ {
		formatDay := time.Now().AddDate(0, 0, i).Format("20060102")
		syncMatch(formatDay)
	}
}
func (f Cricket) SyncLive() {
}

// SyncDelete 获取删除数据
// 返回最近24小时内删除的数据id（比赛、球队、球员、赛事、赛季、阶段），需定时同步
//
// 建议请求频次：1~5min/次
func (f Cricket) SyncDelete() {
	resp := cricket_behaviour2.DeleteApiResponse{}
	queryStr := config.BuildParamsAndUserAndSecret(map[string]interface{}{})
	err := restyclient.GetUrlAndBindRecords(config.CRDelete+queryStr, &resp)
	if err != nil {
		global2.Log.Error("获取删除列表失败: ", err)
		return
	}

	for _, result := range resp.Results {
		typeId, err := cast.ToInt32E(result[0])
		if err != nil {
			global2.Log.Error("解析 删除类型 失败: ", err)
			continue
		}

		deleteIds, err := cast.ToIntSliceE(result[0])
		if err != nil {
			global2.Log.Error("解析 删除ids 失败: ", err)
			continue
		}

		if len(deleteIds) == 0 {
			continue
		}

		// 调用入库
		switch typeId {
		case 2: // 球队
			cricket2.DeleteTeams(deleteIds)
		case 4: // 赛事
			cricket2.DeleteUniqueTournament(deleteIds)
		case 8: // 比赛
			cricket2.DeleteMatch(deleteIds)
			// TODO: 足球 没加 sport_id 作为 删除 条件 ?
			global2.Sport().Where("match_id in ? and sport_id = ?", deleteIds, config.Cricket).Delete(models_sports.MatchFavorite{})
			global2.Sport().Where("match_id in ? and sport_id = ?", deleteIds, config.Cricket).Delete(models_sports.MatchFavoriteStatistics{})
		default:
			global2.Log.Warnf("忽略的 删除项 类型: %d", typeId)
		}
	}
}

var lineupLastId atomic.Int32

func (f Cricket) SyncLineupWork() {
	startTime, endTime := utils.GetDayStart2End()
	lastId := int(lineupLastId.Load())
	ids := cricket2.GetLiveUpMatchIds(startTime, endTime, lastId)
	if len(ids) == 0 {
		global2.Log.Info("数据已刷新完成")
		lineupLastId.Store(0)
		return
	}
	for i, id := range ids {
		resp := cricket_behaviour2.LineUpApiResponse{}
		queryStr := config.BuildParamsAndUserAndSecret(map[string]interface{}{
			"id": id,
		})
		err := restyclient.GetUrlAndBindRecords(config.CRLineUp+queryStr, &resp)
		if err != nil {
			global2.Log.Error("获取更新阵容列表失败: ", err)
			continue
		}
		if resp.Code != 0 {
			global2.Log.Error("获取更新阵容列表失败: ", err)
			continue
		}
		resp.Results.MatchId = id
		// 一次只推送一场
		err = crcache.NewLineUpRedis().PublishLineup(resp.Results)
		if err != nil {
			global2.Log.Error("发送阵容数据到nats失败: ", err)
		}
		lineupLastId.Store(int32(ids[i]))
	}
}

func (f Cricket) SyncRecent() {
	// TODO: 板球 没有 这 接口 ?
}
